package cn.iocoder.yudao.module.ym.job;

import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO;
import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper;
import cn.iocoder.yudao.module.infra.enums.DictDataConstants;
import cn.iocoder.yudao.module.infra.enums.TicketLogRecordConstants;
import cn.iocoder.yudao.module.infra.enums.TicketStatusEnum;
import cn.iocoder.yudao.module.infra.enums.YmMessageEnum;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApiImpl;
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.ym.dal.dataobject.ticket.TicketDO;
import cn.iocoder.yudao.module.ym.dal.dataobject.ticketlog.TicketLogDO;
import cn.iocoder.yudao.module.ym.dal.mysql.ticket.TicketMapper;
import cn.iocoder.yudao.module.ym.dal.mysql.ticketlog.TicketLogMapper;
import cn.iocoder.yudao.module.ym.service.site.SiteService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserNickname;

/**
 * 定时巡检工单
 *
 * @author j-sentinel
 */
@Slf4j
@Component("autoCreateTicketJobA")
public class AutoCreateTicketJobA implements JobHandler {

    @Resource
    private JobMapper jobMapper;

    @Resource
    private TicketMapper ticketMapper;

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private TicketLogMapper ticketLogMapper;

    @Resource
    private WebProperties webProperties;

    @Resource
    private NotifyMessageSendApiImpl notifyMessageSendApi;

    @Resource
    private SiteService siteService;


    @Override
    @TenantIgnore
    public String execute(String param) {
        System.out.println("自动创建巡检工单-----------------------------------" + LocalDateTime.now());
        if (param != null && !param.isEmpty()) {
            JobDO jobDO = jobMapper.selectById(Long.parseLong(param));
            if (jobDO != null) {
                ReentrantLock reentrantLock = new ReentrantLock();
                try {
                    reentrantLock.lock();
                    Integer ticketType = 1;//巡检
                    String inspectionItem = jobDO.getInspectionItem();//检查项
                    Long operatorId = jobDO.getOperatorId();//指派人
                    Integer timeoutHour = jobDO.getTimeoutHour();
                    String operatorName = "";
                    Long tenantId = 0L;
                    Long deptId = 0L;
                    AdminUserDO adminUserDO = adminUserMapper.selectById(operatorId);
                    if (adminUserDO != null) {
                        operatorName = adminUserDO.getNickname();
                        tenantId = adminUserDO.getTenantId();
                        deptId = adminUserDO.getDeptId();
                    } else {
                        return "暂无该指派人";
                    }
                    String siteIds = jobDO.getSiteIds();
                    String[] siteIdsSplit = siteIds.split(",");
                    Long areaId = jobDO.getAreaId();


                    long l = ticketMapper.selectCount(new LambdaQueryWrapper<TicketDO>().apply("DATE(create_time) = CURDATE()"));

                    // 1. 提取固定值到循环外部
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                    String format = LocalDate.now().format(formatter); // 日期前缀只计算一次
                    String ticketDesc = "系统自动创建工单"; // 固定描述
                    int ticketLevel = 1; // 固定优先级
                    Integer ticketStatus = TicketStatusEnum.PENDING.getCode(); // 固定状态


                    // 2. 预计算总工单数量，预分配 List 容量
                    int totalTickets = jobDO.getSiteIds().split(",").length;
                    List<TicketDO> insertList = new ArrayList<>(totalTickets);
                    List<TicketLogDO> insertLogList = new ArrayList<>(totalTickets);

                    // 3. 工单编号优化：预生成前缀 + 高效计数器
                    AtomicLong counter = new AtomicLong(l); // 线程安全计数器
                    String numberPrefix = "WO-" + format + "-";

                    for (String s1 : siteIdsSplit) {
                        TicketDO ticketDO = new TicketDO();
                        ticketDO.setTicketType(ticketType); //工单类型 巡检
                        ticketDO.setTicketStatus(ticketStatus); //待处理
                        ticketDO.setAreaId(areaId);//区域
                        ticketDO.setSiteId(Long.parseLong(s1));//电站
                        ticketDO.setTicketLevel(ticketLevel); //默认低优先级
                        ticketDO.setTicketDesc(ticketDesc);//工单描述
                        ticketDO.setInspectionItem(inspectionItem);//检查项
                        ticketDO.setOperatorId(operatorId); //指派人
                        ticketDO.setDeptId(deptId);
                        ticketDO.setTenantId(tenantId);
                        ticketDO.setTimeoutHour(timeoutHour);
                        ticketDO.setThirdId(2);
                        // 工单编号生成优化：StringBuilder 替代格式化
                        long seq = counter.incrementAndGet();
                        String ticketNumber = new StringBuilder(numberPrefix)
                                .append(String.format("%05d", seq))
                                .toString();
                        ticketDO.setTicketNumber(ticketNumber);
                        insertList.add(ticketDO);
                    }

                    if (!insertList.isEmpty()) {
                        ticketMapper.insertBatch(insertList);
                        for (TicketDO ticketDO : insertList) {
                            //插入日志
                            TicketLogDO ticketLogDO = new TicketLogDO();
                            ticketLogDO.setTicketId(ticketDO.getId());
                            ticketLogDO.setContent(String.format(TicketLogRecordConstants.CREATE_TICKET, "系统定时 ", operatorName));
                            ticketLogDO.setTenantId(tenantId);
                            insertLogList.add(ticketLogDO);
                        }
                        if (!insertLogList.isEmpty()) {
                            ticketLogMapper.insertBatch(insertLogList);
                        }
                        // 发送站内信
                        Map<String, Object> templateParams = new HashMap<>();
                        templateParams.put("siteNames", siteService.getNames(siteIds));
                        templateParams.put("url", webProperties.getAdminUi().getUrl() + "/#/order/my");


                        NotifySendSingleToUserReqDTO notifySendSingleToUserReqDTO = new NotifySendSingleToUserReqDTO();
                        notifySendSingleToUserReqDTO.setUserId(operatorId);
                        notifySendSingleToUserReqDTO.setTemplateCode(YmMessageEnum.TIMING_TICKET_NOTICE.getSmsTemplateCode());
                        notifySendSingleToUserReqDTO.setTemplateParams(templateParams);
                        notifySendSingleToUserReqDTO.setTenantId(tenantId);
                        notifyMessageSendApi.sendSingleMessageToAdminTenant(notifySendSingleToUserReqDTO);
                        return String.format("定时创建巡检工单数量 %s 个", insertList.size());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        }
        return "未创建定时工单";
    }

}
